 /*
    *  Copyright 2004 Thevert Liu  <thevert.liu@gmail.com>
    *
    *  Licensed under the Apache License, Version 2.0 (the "License");
    *  you may not use this file except in compliance with the License.
    *  You may obtain a copy of the License at
    *
    *      http://www.apache.org/licenses/LICENSE-2.0
    *
   *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */

#include <XMLShell.h>


void XMLContext::registNS (const std::string& prefix, const std::string& ns) 
{
    mNamespaces.push(prefix, ns) ;
}

bool XMLContext::getPrefix(const std::string& ns, std::string& prefix) const
{
    return mNamespaces.getFirst(ns, prefix) ;
}

bool XMLContext::getNS(const std::string& prefix, std::string& ns) const
{
    return mNamespaces.getSecond(prefix, ns) ;
}

bool XMLContext::write(std::ostream& os) const
{
    P2PMap<std::string, std::string>::const_iterator it = mNamespaces.begin();
    
    for (;it!=mNamespaces.end();it++) {
        os << " xmlns:" << it->first << ":\"" << it->second << "\"" ;
    }
    
    return true ;
}



template<typename T> 
int clear(std::list<void*>& l)
{
    std::list<void*>::iterator it;
    for (it=l.begin(); it!=l.end(); it++) {
        delete (T*) *it ;
    }
} ;


XMLShell::~XMLShell()
{
    if (mValue) delete mValue ;
    if (mExtraBlock) delete mExtraBlock ;
    clear<AttributeNode>(mAttributes) ;
    clear<ElementNode>(mElements) ;
}

bool XMLShell::registAttributeNS(const std::string& ns, const std::string& name, IShellAttribute* attr) 
{
//    s3debug << "Regist Attribute:" << ns << ":" << name << ENDL ;
    if (attr==NULL) {
        log << "Regist Attribute is empty!" << name  ;
        return false ;
    }
    if (getAttributeNS(ns, name)!=NULL) {
        log << "Regist Attribute is empty!" << ns << ":" << name  ;
        return false ;
    }
    
    mAttributes.push_back(new IXMLShell::AttributeNode(ns, name, attr)) ;
    
    return true ;
}

bool XMLShell::registElementNS(const std::string& ns, const std::string& name, IShellElement* element) 
{
    if (element==NULL) {
        return false ;
    }
    
    if (getElementNS(ns, name)!=NULL) {
        return false ;
    }
    
    mElements.push_back(new IXMLShell::ElementNode(ns, name, element)) ;
    return true ;
}

bool XMLShell::registAttribute(const std::string& name, IShellAttribute* attr) 
{
	return registAttributeNS("", name, attr) ;
}

bool XMLShell::registElement(const std::string& name, IShellElement* element)
{
    return registElementNS("", name, element) ;
}

bool XMLShell::registValue(IValue* value) 
{
    if (mExtraBlock) {
		return false ;
	}

	mValue = value;
	
	return true;
}

bool XMLShell::registExtraBlock(IExtraBlock * value) 
{
	if (mValue) {
		return false ;
	}
	
	mExtraBlock = value;
	return true ;
}

IExtraBlock* XMLShell::getExtraBlock() 
{
    return mExtraBlock ;
}

IValue*      XMLShell::getValue() 
{
    return mValue ;
}

IShellAttribute* XMLShell::getAttribute(const std::string& name) 
{
    return getAttributeNS("", name) ;
}

IShellAttribute* XMLShell::getAttributeNS(const std::string& ns, const std::string& name) 
{
    for (VList::iterator it=mAttributes.begin();
        it!=mAttributes.end(); it++) {
        IXMLShell::AttributeNode& node = *(IXMLShell::AttributeNode*)*it ;
        if (ns==node.prefix && name==node.name) {
            return node.adapter ;
        }
    }
    
    return NULL ;
}

IShellElement* XMLShell::getElement(const std::string& tagName) 
{
    return getElementNS("", tagName) ;
}

IShellElement* XMLShell::getElementNS(const std::string& ns, const std::string& tagName) 
{
    for (VList::iterator it=mElements.begin();
        it!=mElements.end(); it++) {
        ElementNode& node = *(ElementNode*)*it ;
        if (ns==node.prefix && tagName==node.name) {
            return node.adapter ;
        }
    }
    
    return NULL ;
}



bool XMLShell::browse(IParamHandler<IXMLShell::AttributeNode&>* handler)
{
//    s3debug << "Attribute number:" << mAttributes.size() << ENDL ; 
    for (VList::iterator it=mAttributes.begin(); 
         it!=mAttributes.end(); it++)  {
        AttributeNode* node = (AttributeNode*) *it ;
        if (handler->handle(*node)!=0) {
            log << "handle attribute failed:" << node->name  ;
            return false ;
        }
    }
    return true ;
}

bool XMLShell::browse(IParamHandler<IXMLShell::ElementNode&>*  handler) 
{
//    s3debug << "Element number:" << mElements.size() << ENDL ;
    
    for (VList::iterator it=mElements.begin(); 
         it!=mElements.end(); it++)  {
        ElementNode* node = (ElementNode*) *it ;
        if (handler->handle(*node)!=0) {
            log << "handle ELEMENT failed:" << node->name  ;
            return false ;
        }
    }
    
    return true ;
}

bool XMLShell::isEmpty() const
{
    if (mExtraBlock==NULL && mValue==NULL && mElements.size()==0) {
        return true ;
    }
    
    return false ;
}

